﻿namespace ChessToys.QueensProblem.Cli
{
    using System;
    using System.Collections.Generic;
    using System.Reflection;
    using ChessToys;
    using ChessToys.QueensProblem;

    public class Cli
    {
        static void Main(String[] args)
        {
            Arguments arguments = GetArguments(args);
            if (arguments != null)
            {
                Console.WriteLine(String.Format("Solving the Queens Problem for n = {0}...", arguments.N));
                Timer timer = new Timer();
                try
                {
                    // solve problem and get solutions
                    ISet<Board> solutions = arguments.QueensProblemSolver.Solve(arguments.N);
                    // print solution count out
                    Console.WriteLine(String.Format("There are {0} solutions. Took {1}.", solutions.Count, timer));
                    // should print details
                    if (arguments.PrintStyle != PrintStyle.None)
                    {
                        IEnumerator<Board> enumerator = solutions.GetEnumerator();
                        while (enumerator.MoveNext())
                        {
                            switch (arguments.PrintStyle)
                            {
                                case PrintStyle.fen:
                                    Console.WriteLine(String.Format("  {0}", enumerator.Current.Fen));
                                    break;
                                case PrintStyle.board:
                                    enumerator.Current.ToConsole();
                                    break;
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(String.Format("Error while solving: {0}", e.Message));
                }
            }
        }

        private static Arguments GetArguments(string[] args)
        {
            // default arguments
            int n = 8;
            IQueensProblemSolver solver = new BFSQueensProblemSolver();
            PrintStyle printStyle = PrintStyle.fen;
            // try to pars command line arguments
            for (int i = 0; i < args.Length; i++)
            {
                switch (args[i])
                {
                    case "-n":
                        if (i + 1 >= args.Length)
                        {
                            Console.WriteLine("Missing argument for \"-n\".");
                            return null;
                        }
                        try
                        {
                            n = int.Parse(args[i + 1]);
                        }
                        catch (FormatException)
                        {
                            Console.WriteLine(String.Format("\"{0}\" is not a number.", args[i+1]));
                            return null;
                        }
                        i++;
                        break;
                    case "-solver":
                        if (i + 1 >= args.Length)
                        {
                            Console.WriteLine("Missing argument for \"-solver\".");
                            return null;
                        }
                        Assembly assembly = Assembly.GetAssembly(typeof(IQueensProblemSolver));
                        Object obj = null;
                        try
                        {
                            obj = assembly.CreateInstance(args[i + 1]);
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine(String.Format("Unable to load solver: {0}", e.Message));
                            return null;
                        }
                        if (obj == null)
                        {
                            Console.WriteLine(String.Format("Unable to find solver named \"{0}\".", args[i+1]));
                            return null;
                        }
                        i++;
                        solver = obj as IQueensProblemSolver;
                        if (solver == null)
                        {
                            Console.WriteLine(String.Format("\"{0}\" is no {1}.", obj, typeof(IQueensProblemSolver)));
                            return null;
                        }
                        break;
                    case "-print":
                        if (i + 1 >= args.Length)
                        {
                            Console.WriteLine("Missing argument for \"-print\".");
                            return null;
                        }
                        try
                        {
                            printStyle = (PrintStyle)Enum.Parse(typeof(PrintStyle), args[i + 1]);
                        }
                        catch (ArgumentException)
                        {
                            Console.WriteLine(String.Format("Print style \"{0}\" unknown.", args[i + 1]));
                            return null;
                        }
                        i++;
                        break;
                    case "-help":
                        Console.WriteLine("ChessToys.QueensProblem.Cli options:");
                        Console.WriteLine("  -help              prints this message");
                        Console.WriteLine("  -version           prints version informations");
                        Console.WriteLine("  -n [n]             specify the size of the problem to solve (default is 8)");
                        Console.WriteLine("  -solver [solver]   specify the solver implementation (default is ChessToys.QueensProblem.BFSQueensProblemSolver)");
                        Console.WriteLine("  -print [style]     prints the found solutions (style = fen | board");
                        return null;
                    case "-version":
                        Console.WriteLine("ChessToys.QueensProblem.Cli version 1.1.0");
                        return null;
                }
            }
            // return arguments
            return new Arguments(n, solver, printStyle);
        }
    }
}
